use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use once_cell::sync::Lazy;
use tokio::runtime::Runtime;
use serde_json::Value;

static RUNTIME: Lazy<Runtime> = Lazy::new(|| {
    Runtime::new().expect("Failed to create Tokio runtime")
});

async fn fetch_weather_data(city: &str) -> Result<String, Box<dyn std::error::Error>> {
    let api_key = "YOUR_API_KEY"; // ⚠️ 替换为你自己的 OpenWeatherMap API Key
    let url = format!(
        "https://api.openweathermap.org/data/2.5/weather?q={}&appid={}",
        city, api_key
    );
    let res = reqwest::get(&url).await?;
    let body = res.text().await?;
    let json: Value = serde_json::from_str(&body)?;
    let weather_description = json["weather"][0]["description"].as_str().unwrap_or("unknown");
    Ok(weather_description.to_string())
}

#[no_mangle]
pub extern "C" fn get_weather_sync(city: *const c_char) -> *mut c_char {
    let c_str = unsafe {
        assert!(!city.is_null());
        CStr::from_ptr(city)
    };

    let city_str = match c_str.to_str() {
        Ok(s) => s,
        Err(_) => return std::ptr::null_mut(),
    };

    let result = RUNTIME.block_on(fetch_weather_data(city_str));
    match result {
        Ok(description) => CString::new(description).unwrap().into_raw(),
        Err(_) => std::ptr::null_mut(),
    }
}

#[no_mangle]
pub extern "C" fn free_string(s: *mut c_char) {
    if !s.is_null() {
        unsafe {
            drop(CString::from_raw(s));
        }
    }
}

